home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / linux_bo / netboot.zoo / newdrive / net3com.asm next >
Encoding:
Assembly Source File  |  1993-05-04  |  24.7 KB  |  944 lines

  1. ;  3COM 3C501 driver code
  2. ;  Tim Krauskopf
  3. ;
  4. ;  This version is virtually unused, replaced by the driver version 
  5. ;  which handles all of the different ioaddrs and interrupts.
  6. ;
  7. ;****************************************************************************
  8. ;*                                                                          *
  9. ;*                                                                          *
  10. ;*      part of NCSA Telnet                                                 *
  11. ;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  12. ;*                                                                          *
  13. ;*      National Center for Supercomputing Applications                     *
  14. ;*      152 Computing Applications Building                                 *
  15. ;*      605 E. Springfield Ave.                                             *
  16. ;*      Champaign, IL  61820                                                *
  17. ;*                                                                          *
  18. ;*                                                                          *
  19. ;****************************************************************************
  20. ;
  21.     TITLE    NETSUPPORT -- LOW LEVEL DRIVERS FOR ETHERNET
  22. ;
  23. ;  Assembler support for interrupt-driven Ethernet I/O on the PC
  24. ;
  25. ;  Will read and write packets from the 2K packet buffer on the
  26. ;  Etherlink card.  Provides hooks for higher layer protocols.
  27. ;
  28.     NAME    NET3COM
  29.     include model.inc
  30.  
  31. ;
  32. ;  Equates for controlling the 3COM board
  33. ;
  34. ICTRL    EQU    020H        ; 8259 interrupt control register
  35. IMASK    EQU    021H        ; 8259 interrupt mask register
  36. BASEA    EQU    300H        ; Base I/O address on PC I/O bus
  37. ENDOFI    EQU    020H        ; end-of-interrupt
  38. ;
  39. ;  Controller registers
  40. ;
  41. EADDR    EQU    BASEA+0H    ; Network address for hardware checking
  42. ;   takes six bytes, this is the address that the Ethernet board will
  43. ;   match to find packets on the net.  (0-5h)
  44. ;
  45. EREC    EQU    BASEA+6H    ; Receive status (read)
  46.                 ; Receive command (write)
  47. ESEND    EQU    BASEA+7H    ; Transmit status (read)
  48.                 ; Transmit command (write)
  49. EGLOW    EQU    BASEA+8H    ; General purpose pointer for R/W to 
  50.                 ; packet buffer, low byte
  51. EGHI    EQU    BASEA+9H    ; high byte, total of 11 bits for 2K buffer
  52. ERLOW    EQU    BASEA+0AH    ; Receive pointer, set by board (read) low byte
  53.                 ; Receive buffer pointer clear (write)
  54. ERHI    EQU    BASEA+0BH    ; high byte of Receive pointer
  55. EPROM    EQU    BASEA+0CH    ; PROM window address
  56.         ;     DH ??
  57. EAUX    EQU    BASEA+0EH    ; Auxiliary Status (read)
  58.                 ; Aux Command (write)
  59. EBUF    EQU    BASEA+0FH    ; Buffer window (where to I/O to net)
  60. ;
  61. ;  Transmit command options
  62. ;     what conditions we wish to be interrupted on after transmit
  63. ;
  64. EDTUNDER  EQU    01H        ; Detect underflow (bad CRC), not used
  65. EDTCOLL    EQU    02H        ; Detect collision on xmit
  66. EDTC16    EQU    04H        ; Detect 16 consecutive collisions (net down)
  67. EDTOK    EQU    08H        ; Detect successful transmission
  68.                 ; other 4 bits unused in this reg
  69. EXMITNORM  EQU    00H        ; Normal use for interrupt-driven XMIT
  70. ;
  71. ;  Transmit status results
  72. ;
  73. ;  Use same values as commands, 08h means OK to xmit again
  74. ;
  75. ;*****************************
  76. ;  Receive Command Options
  77. ;
  78. ;    If something is not detected for, the receiver automatically discards
  79. ;        those packets.
  80. ;
  81. EDTOVER    EQU    01H        ; Detect Overflow condition
  82. EDTFCS    EQU    02H        ; Detect FCS error, bad CRC on packet
  83. EDTDRB    EQU    04H        ; Detect dribble errors and accept them
  84. EDTSHORT EQU    08H        ; Detect short frames (< 60 bytes)
  85. EDTEOF    EQU    10H        ; Detect no overflow (end-of-frame found)
  86. EGOOD    EQU    20H        ; Accept good frames 
  87. ; four values legal for the last two bits:
  88. ECLOSE    EQU    00H        ; Turn off receiver
  89. EGETALL    EQU    40H        ; Get all packets, no matter what address
  90. EBROAD    EQU    80H        ; get those for me or for broadcast
  91. EMULTI    EQU    0C0H        ; get those for me or for multicast
  92. EWANT    EQU    0A0h        ; EGOOD OR EBROAD
  93.                 ; which packets we will look for on net
  94. ;
  95. ;  Receive Status results
  96. ;
  97. ;  errors are not detected unless asked for...otherwise the board just
  98. ;  won't take bad packets off of the net.
  99. ;
  100. ERROVER    EQU    01H        ; overflow error
  101. ERRFCS    EQU    02H        ; FCS (checksum) error
  102. ERRDRB    EQU    04H        ; Dribble error
  103. ERRSHORT  EQU    08H        ; Short frame error
  104. ENOOVER    EQU    10H        ; Received without overflow error 
  105.                 ; means that we didn't miss any by being slow
  106. ;EGOOD    EQU    20H        ; as above, we received a valid frame
  107. ; undefined 40h
  108. ESTALE    EQU    80H        ; stale receive condition, already read me
  109. ;
  110. ;  Aux command register
  111. ;
  112. EIRE    EQU    01H        ; interrupt request enable (no DMA) new boards
  113. EBADFCS    EQU    02H        ; create bad checksum for testing only
  114. ;
  115. ;  Next two bits tell who has access to packet buffer
  116. ;
  117. EBUS    EQU    00H        ; System bus has control of buffer
  118. EXMIT    EQU    04H        ; Transmit packet in buffer, auto kick
  119.                 ; back to recieve status
  120. EGETEM    EQU    08H        ; Receive state, look for packets
  121. ELOOP    EQU    0CH        ; Transmit and loopback into xmit buffer
  122. ;  10H  unused
  123. EDMA    EQU    20H        ; Starts a DMA xfer
  124. ERIDE    EQU    40H        ; Interrupt and DMA enable
  125. ERESET    EQU    80H        ; Reset the Ethernet board
  126. ;
  127. ;  Aux status register
  128. ;
  129. ERBUSY    EQU    01H        ; Receive busy, receiver looking for packets
  130. ;               02H        ; echos command status EBADFCS
  131. ;               04,08h        ; echos command status for EXMIT,EGETEM,EBUS
  132. EDMADONE  EQU    10H        ; goes to one when DMA finishes
  133. ;               20H        ; echos DMA request bit
  134. ;               40h        ; echos RIDE bit
  135. EXBUSY    EQU    80H        ; for polled xmit, goes to 0 when xmit is done
  136. ;
  137. ;
  138. ;  Macros for in and out
  139. ;
  140. MOUT    MACRO    REG,STUFF       ; one byte to the given I/O register
  141.     MOV    DX,REG
  142.     MOV    AL,STUFF
  143.     OUT    DX,AL
  144.     ENDM
  145. ;
  146. MOUTW    MACRO    REG,LO,HI      ; two bytes to the I/O double port
  147.     MOV    DX,REG
  148.     MOV    AL,LO
  149.     OUT    DX,AL
  150.     INC    DX
  151.     MOV    AL,HI
  152.     OUT    DX,AL
  153.     ENDM
  154. ;
  155. MIN    MACRO    REG             ; get one byte to al
  156.     MOV    DX,REG
  157.     IN    AL,DX
  158.     ENDM
  159.  
  160. ifdef Microsoft
  161. ;DGROUP    group    _DATA
  162. ;_DATA    segment    public 'DATA'
  163. ;    assume    DS:DGROUP
  164.     .data
  165. else
  166.     DSEG
  167. endif
  168. ;
  169. ;  The pointers below are actually DWORDs but we access them two
  170. ;  bytes at a time.
  171. ;
  172. ifdef Microsoft
  173. ;    EXTRN    _RSTAT:BYTE    ; last status from read
  174. ;    EXTRN    _BUFPT:WORD    ; current buffer pointer
  175. ;    EXTRN    _BUFORG:WORD    ; pointer to beginning of buffer
  176. ;    EXTRN    _BUFEND:WORD    ; pointer to end of buffer
  177. ;    EXTRN    _BUFREAD:WORD    ; pointer to where program is reading
  178. ;    EXTRN    _BUFBIG:WORD    ; integer, how many bytes we have
  179. ;    EXTRN    _BUFLIM:WORD    ; integer, max bytes we can have
  180. ;
  181. ; Seems to work only this way //jkp
  182.     PUBLIC    _RSTAT,_BUFPT,_BUFORG,_BUFEND,_BUFREAD,_BUFBIG,_BUFLIM,OFFS
  183. _RSTAT    DB    00H         ; last status from read
  184. _BUFBIG    DW    00H        ; buffer space used
  185. _BUFLIM    DW    05000H        ; buffer space limit
  186. _BUFPT    DW    00000H        ; where buffer pointer is, initialized safely
  187. _BUFDS    DW    0a000H        ; where buffer is, ds
  188. _BUFORG    DW    00000H        ; start of buffer space
  189. _BUFDS2    DW    0a000H        ; another ds
  190. _BUFEND    DW    06000H        ; end limit of allowable buffer space
  191. _BUFDS3    DW    0a000H
  192. _BUFREAD    DW    00000H        ; where the read pointer is
  193. _BUFDS4    DW    0a000H
  194. else
  195.     EXTRN    RSTAT:BYTE    ; last status from read
  196.     EXTRN    BUFPT:WORD    ; current buffer pointer
  197.     EXTRN    BUFORG:WORD    ; pointer to beginning of buffer
  198.     EXTRN    BUFEND:WORD    ; pointer to end of buffer
  199.     EXTRN    BUFREAD:WORD    ; pointer to where program is reading
  200.     EXTRN    BUFBIG:WORD    ; integer, how many bytes we have
  201.     EXTRN    BUFLIM:WORD    ; integer, max bytes we can have
  202. endif
  203.  
  204. SAVECS    DW    00H        ; where to save the old interrupt ptr
  205. SAVEIP    DW    00H
  206. OLDMASK    DB    00H        ; save interrupt controller mask
  207. DEAF    DB    00H        ; when we can't handle any more packets
  208. OFFS    DW    00H        ; how many times the handler was turned off
  209. ;
  210. ;  use variables to access IRQ3 or IRQ5
  211. ;  3 is COM2, 5 is LPT2
  212. ;
  213. ;WHICHINT  EQU    4*0Bh        ; Interrupt for interrupt I/O on IRQ3
  214. ;WHICHINT  EQU    4*0Dh        ; Interrupt for interrupt I/O on IRQ5
  215. ;TURNOFF  EQU      08H          ; IRQ3 bit mask for 8259 controller (1<<3)
  216. ;TURNOFF  EQU      020H            ; IRQ5 bit mask for 8259 controller (1<<5)
  217. ;TURNON    EQU    0F7H        ; IRQ3 enable bit mask for 8259 controller
  218. ;TURNON    EQU    0DFH        ; IRQ5 enable bit mask for 8259 controller
  219. INTNUM    DB    0BH        ; Defaults to IRQ3, interrupt handler 0bh
  220. WHICHINT  DW    4*0BH        ; ETOPEN can change these values
  221. TURNOFF    DB    08H
  222. TURNON    DB    0F7H
  223.  
  224.  
  225. MYDS    DW    00H        ; the data segment for this assembly code
  226. ICNT    DB      00H
  227.  
  228.     assume CS:DGROUP
  229.  
  230. IHAND:                       ; not a public name, only handles ints
  231.     STI
  232.     PUSH    DS
  233.     PUSH     ES
  234.     PUSH    AX
  235.     PUSH    BX
  236.     PUSH    CX
  237.     PUSH    DX
  238.     PUSH    DI
  239.     CLD            ; all moves will be forward
  240. ;
  241. ;  SET UP CORRECT DS
  242. ;
  243.     MOV    DS,CS:MYDS        ; get correct ds
  244. ifdef Microsoft
  245.     MOV    AX,word ptr [_BUFPT+2]    ; buffer's ds
  246.     MOV DI,_BUFPT       ; where buffer is
  247. else
  248.     MOV    AX,word ptr [BUFPT+2]    ; buffer's ds
  249.     MOV DI,BUFPT        ; where buffer is
  250. endif
  251.     MOV    ES,AX
  252. ;
  253. ;  check for buffer overrun or catching up with reader
  254. ;
  255. ;  implicit 64K max buffer, should stop before 64K anyway
  256. ;
  257. ifdef Microsoft
  258.     MOV    AX,_BUFBIG    ; how much stuff is in buffer
  259. else
  260.     MOV    AX,BUFBIG    ; how much stuff is in buffer
  261. endif
  262. ifdef Microsoft
  263.     MOV    BX,_BUFLIM    ; what is our size limit?
  264. else
  265.     MOV    BX,BUFLIM    ; what is our size limit?
  266. endif
  267.     CMP    AX,BX
  268.     JNA    ISROOM        ; we are ok
  269. ;
  270. ;  no room at the Inn.  turn off receiver
  271. ;
  272.     MOUT    EAUX,EBUS+ERIDE    ; refuse to read more packets until restarted
  273.  
  274.     MIN    EREC        ; must clear interrupt
  275.  
  276.     MOV    AL,1        ; set flag
  277.     MOV    DEAF,AL        ; we are now deaf, read routine must restart
  278.  
  279.     JMP SHORT ENDINT      ; can't do much, we lose packets until restarted
  280.  
  281. ;
  282. ;  wrap pointer around at end, we know that we have room
  283. ;
  284. ISROOM:
  285. ifdef Microsoft
  286.     MOV    DX,_BUFEND    ; right before 2K safety area
  287. else
  288.     MOV    DX,BUFEND    ; right before 2K safety area
  289. endif
  290.     CMP    DX,DI        ; see if pointer is over limit
  291.     JA    OKAYREAD    ; we are not at wrap-around
  292.  
  293. ifdef Microsoft
  294.     MOV    AX,_BUFORG    ; wrap to here
  295. else
  296.     MOV    AX,BUFORG    ; wrap to here
  297. endif
  298. ifdef Microsoft
  299.     MOV    _BUFPT,AX    ; wrap-around
  300. else
  301.     MOV    BUFPT,AX    ; wrap-around
  302. endif
  303.     MOV    DI,AX        ; di also
  304. ;
  305. ;  here, DI contains where we want to put the packet.
  306. ;
  307. OKAYREAD:
  308.  
  309. ;    MOV    CX,10        ; give it a few tries
  310.  
  311. IFINDONE:
  312. ;    MIN    EAUX        ; get status to al
  313. ;    AND    AL,ERBUSY    ; is it still in receive state or done?
  314. ;    JZ    IREADONE    ; done, can read it
  315. ;    LOOP    IFINDONE
  316. ;    MIN    EREC
  317. ;    AND    AL,ESTALE
  318. ;    JZ    IREADONE
  319. ;    jmp    ireadone
  320.  
  321. ;    MOV    AX,0        ; no packet yet, spurious int, return
  322. ;    STOSB
  323.  
  324. ;    MIN    EREC        ; clear interrupt condition
  325. ;    MIN    ESEND        ; in case it was an xmit spurious int
  326. ;    JMP    STOPINT
  327. ;
  328. IREADONE:
  329.     MOUT    EAUX,EBUS+ERIDE    ; turn off receive, give buffer to bus
  330.     MOUTW    EGLOW,0,0    ; clear general purpose pointer for read
  331.     MIN    EREC        ; get status to al, clears read
  332.  
  333.     MOV    DX,ERLOW    ; receive buffer pointer
  334.     IN    AL,DX
  335.     MOV    CL,AL        ; save low byte
  336.     INC    DX
  337.     IN    AL,DX
  338.     MOV    CH,AL        ; save high byte
  339.  
  340.     MOV    BX,CX           ; save another copy of the length
  341.     OR    BX,BX        ; check for non-zero
  342.     JZ    STOPINT        ; no packet
  343.     
  344.     MOV    AX,BX        ; save length in buffer, before packet
  345.     STOSW
  346.  
  347.     MOV    DX,EBUF        ; window to the data
  348.  
  349. IDOBYTES:
  350.     IN    AL,DX        ; get a byte
  351.     STOSB            ; save it to es:di
  352.     LOOP     IDOBYTES
  353. ;
  354. ;
  355. ;  DI now contains updated value for BUFPT, BX contains size of packet
  356. ;
  357. ifdef Microsoft
  358.     MOV    _BUFPT,DI    ; it is here, now
  359. else
  360.     MOV    BUFPT,DI    ; it is here, now
  361. endif
  362.  
  363. ifdef Microsoft
  364.     MOV    AX,_BUFBIG    ; total amount of stuff in buffer
  365. else
  366.     MOV    AX,BUFBIG    ; total amount of stuff in buffer
  367. endif
  368.     ADD    AX,BX
  369.     INC    AX
  370.     INC    AX        ; to cover the length value
  371. ifdef Microsoft
  372.     MOV    _BUFBIG,AX    ; after adding in current packet size
  373. else
  374.     MOV    BUFBIG,AX    ; after adding in current packet size
  375. endif
  376. ;
  377. ;  signs that something is actually happening - used for debugging
  378. ;
  379. ;    MOV    AX,0B000H       ; screen
  380. ;    MOV    ES,AX
  381. ;    MOV    DI,3998        ; lower right corner
  382. ;    INC    ICNT
  383. ;    MOV    Al,ICNT    ; character
  384. ;    STOSB
  385.  
  386. ;
  387. ;  set up to read the next packet from the net
  388. ;
  389. STOPINT:
  390.     MOUT    ERLOW,0        ; clear receive buffer pointer
  391.     MOUT    EAUX,EGETEM+ERIDE    ; set receive bit in aux
  392.  
  393. ENDINT:
  394.  
  395.     MOUT    ICTRL,ENDOFI    ; signal end of interrupt
  396.     POP    DI
  397.     POP    DX
  398.     POP    CX
  399.     POP    BX
  400.     POP    AX
  401.     POP    ES
  402.     POP    DS
  403.     IRET
  404.  
  405.  
  406. ifdef Microsoft
  407. ;_DATA    ends
  408. else
  409.     ENDDS
  410. endif
  411. ;
  412. ;
  413. ;
  414. ;   The subroutines to call from C
  415. ;
  416. ifdef Microsoft
  417. ;_TEXT    segment    public    'CODE'
  418. ;    assume CS:_TEXT
  419.     .code
  420.     PUBLIC    _E3RECV,_E3ETOPEN,_E3ETCLOSE,_E3GETADDR,_E3SETADDR,_E3XMIT,_E3ETUPDATE
  421. else
  422.     PSEG
  423.     PUBLIC    E3RECV,E3ETOPEN,E3ETCLOSE,E3GETADDR
  424.     PUBLIC    E3SETADDR,E3XMIT,E3ETUPDATE
  425. endif
  426.  
  427. ;******************************************************************
  428. ;  ETOPEN
  429. ;     Initialize the Ethernet board, set receive type.
  430. ;
  431. ;  usage:  etopen(s,irq,addr,ioaddr)
  432. ;           char s[6];       ethernet address
  433. ;           int irq,addr,ioaddr;     
  434. ;                interrupt number, base mem address (unused) and
  435. ;                i/o address to use (currently unused)
  436. ;
  437. ;
  438. START_PROC    E3ETOPEN
  439.     PUSH    BP
  440.     MOV    BP,SP
  441.     PUSH    SI
  442.     MOUT    EAUX,ERESET    ; reset the board
  443.     MOUT    EAUX,0          ; Clear the reset bit, otherwise keeps resetting
  444. ;
  445. ;  check the parameters for interrupt and dma
  446. ;
  447.     MOV    AX,[BP+X+4]    ; interrupt number
  448.     CMP    AL,5        ; If not 5, then use 3
  449.     JNZ    USE3
  450.     MOV    INTNUM,0DH    ; Interrupt # for handler for IRQ5
  451.     MOV    WHICHINT,4*0DH    ; Interrupt handler location in vector table
  452.     MOV    TURNOFF,020H    ; mask for interrupt controller for IRQ5
  453.     MOV    TURNON,0DFH    ; opposite mask, for interrupt controller
  454. USE3:
  455.     MOV    AX,[BP+X+6]    ; dma channel to use
  456.     CMP    AL,3        ; if not 3, then use 1
  457.     JNZ    USE1
  458. ;
  459. ; Add DMA values for channel 3 here later
  460. ;  probably never going to use DMA for this board - unreliable so far
  461. ;
  462. USE1:
  463. ;
  464. ;  install the interrupt handler
  465. ;
  466.     CALL    IINST        ; do the patching of the interrupt table
  467. ;
  468. ;  set up the net address
  469. ;
  470.     PUSH     DS        ; save mine
  471.     MOV    AX,[BP+X+2]    ; get new one
  472.     MOV    DS,AX           ; set new one
  473.     MOV    SI,[BP+X]    ; get pointer, ds:si is ready
  474.     ;
  475.     MOV    CX,6
  476.     MOV    DX,EADDR    ; get base i/o reg for setting address
  477.     CLD
  478. SADDR:
  479.     LODSB            ; get next one
  480.     OUT    DX,AL        ; send it
  481.     INC    DX        ; next position
  482.     LOOP    SADDR        ; do 6 times
  483.  
  484.     POP    DS        ; get back DS of local data
  485. ;
  486. ;  enable interrupts here with interrupt handler 
  487. ;  already set up.
  488. ;
  489.     MOUT    ESEND,0        ; xmit command = 0 for no interrupts
  490.     IN    AL,DX
  491.  
  492.     MOUT    EREC,EWANT    ; Set receiver for which packets we want
  493.     IN    AL,DX        ; reset 'stale'
  494.  
  495.     MOUT    ERLOW,0        ; Clear the receive buffer pointer
  496.  
  497.     CLI
  498.     MOUT    EAUX,EGETEM+ERIDE    ; Set for receive, interrupts
  499.  
  500.     MIN    IMASK        ; get current int enable mask
  501.     MOV    BL,AL        ; save a copy
  502.     AND    AL,TURNON    ; force bit for etherlink board off
  503.     OUT    DX,AL        ; put back the byte, IRQ enabled
  504.  
  505.     STI
  506.     AND    BL,TURNOFF    ; isolate this bit only from oldmask
  507.     MOV    OLDMASK,BL    ; save it
  508. ;
  509.     POP    SI
  510.     POP    BP
  511.     XOR    AX,AX
  512.     RET
  513. END_PROC    E3ETOPEN
  514. ;
  515. ;******************************************************************
  516. ;  SETADDR
  517. ;    set the Ethernet address on the board to 6 byte ID code
  518. ;
  519. ;   usage:   setaddr(s,basea,ioa);
  520. ;             char s[6];           ethernet address to use
  521. ;             int basea;           shared memory base address (unused)
  522. ;             int ioa;             io address for board (unused)
  523. ;
  524. START_PROC    E3SETADDR
  525.     PUSH    BP
  526.     MOV    BP,SP
  527.     PUSH    DS
  528.     PUSH    SI
  529.     MOV    AX,[BP+X+2]
  530.     MOV    DS,AX
  531.     MOV    SI,[BP+X]    ; address of buffer to read
  532. ;
  533.     MOV    CX,6
  534.     MOV    DX,EADDR    ; get base i/o reg for setting address
  535.     CLD
  536. SADDR2:
  537.     LODSB            ; get next one
  538.     OUT    DX,AL        ; send it
  539.     INC    DX        ; next position
  540.     LOOP    SADDR2        ; do 6 times
  541.  
  542.     POP    SI
  543.     POP    DS
  544.     POP    BP
  545.     RET
  546. END_PROC    E3SETADDR
  547. ;
  548. ;*******************************************************************
  549. ;  GETADDR
  550. ;     get the Ethernet address off of the board
  551. ;
  552. ;   usage:  getaddr(s,address,ioaddr);
  553. ;    char s[6];           will get six bytes from the PROM
  554. ;       int address;
  555. ;       int ioaddr;     (unused here) mem address and ioaddress to use
  556. ;
  557. START_PROC    E3GETADDR
  558.     PUSH    BP
  559.     MOV    BP,SP
  560.     PUSH    DI
  561.     PUSH     ES        ; save mine
  562.     MOV    AX,[BP+X+2]    ; get new one
  563.     MOV    ES,AX           ; set new one
  564.     MOV    DI,[BP+X]    ; get pointer, es:di is ready
  565.     ;
  566.     MOV    BX,0            ; start location 
  567.     MOV    CX,EPROM    ; address window
  568. GADDR:
  569.     CLD
  570.     MOUTW    EGLOW,BL,BH      ; set gp to the right value
  571.     MIN    CX        ; get value from prom address window
  572.     STOSB                   ; put into given buffer
  573.     INC    BX        ; next position
  574.     CMP    BX,6
  575.     JNZ     GADDR          ; do 6 times
  576.     POP     ES
  577.     POP    DI
  578.     POP    BP        
  579.     RET
  580. END_PROC    E3GETADDR
  581. ;
  582. ;***********************************************************************
  583. ;  ETCLOSE
  584. ;        shut it down, remove the interrupt handler
  585. ;
  586. ;  usage:  etclose();
  587. ;
  588. ;
  589. START_PROC    E3ETCLOSE
  590.     CLI
  591.     MOUT    EAUX,ERESET    ; Turn off all pendings, cause reset
  592.     MOUT    EAUX,0          ; Turn off reset
  593. ;
  594. ;
  595. ;  mask out IRQ on interrupt controller
  596. ;
  597.     MIN    IMASK        ; get current mask
  598.     OR    AL,TURNOFF    ; force that bit on
  599.     OUT    DX,AL        ; send it back to controller
  600.     STI
  601.  
  602.     CALL    DEINST        ; restore old interrupt handler
  603.  
  604.     MOV    BL,OLDMASK    ; get back saved setting of irq
  605.     NOT    BL        ; flip it
  606.     CLI
  607.     MIN    IMASK
  608.     AND    AL,BL        ; restore setting of that bit
  609.     OUT    DX,AL
  610.     STI    
  611.     RET
  612. END_PROC E3ETCLOSE
  613. ;
  614. ;************************************************************************
  615. ;   Receive
  616. ;   This is a CPU hook for boards that must be polled before we can
  617. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  618. ;
  619. ;   The 3COM 3C501 version uses interrupts, so this routine is a NOP
  620. ;   for this board.
  621. ;
  622. ;    usage:  recv();
  623. ;
  624. START_PROC    E3RECV
  625.     RET            ; for compatibility with other drivers
  626. END_PROC    E3RECV
  627.  
  628. ifdef unused_code
  629. ;      This version is unused.  It is a polled receive which is nearly
  630. ;      useless with this board.  It hasn't been debugged yet, either.
  631. ;             char *where;      at least 2048 bytes of room
  632. ;             returns # bytes in packet, -1 if no packet available
  633.     PUSH    BP
  634.     MOV    BP,SP
  635.     PUSH    ES
  636.     MOV    AX,[BP+X+2]    ; get new es value
  637.     MOV    ES,AX
  638.     MOV    DI,[BP+X]    ; set di for later movement
  639.     ;
  640.     MOV    CX,10        ; give it a few tries
  641.  
  642. FINDONE:
  643.     MIN    EAUX        ; get status to al
  644.     MOV    STAT,AL
  645.     AND    AL,ERBUSY    ; is it still in receive state or done?
  646.     JZ    READONE        ; done, can read it
  647.     LOOP    FINDONE
  648.  
  649.     MOV    AX,-1        ; no packet yet, return
  650.     POP    ES
  651.     POP    BP
  652.     RET
  653. ;
  654. READONE:
  655.     MOUT    EAUX,EBUS    ; turn off receive, give buffer to bus
  656.     MOUTW    EGLOW,0,0    ; clear general purpose pointer for read
  657.  
  658.     MOV    DX,ERLOW    ; receive buffer pointer
  659.     IN    AL,DX
  660.     MOV    CL,AL        ; save low byte
  661.     INC    DX
  662.     IN    AL,DX
  663.     MOV    CH,AL        ; save high byte
  664.  
  665.     MOV    BX,CX           ; save another copy of the length
  666.  
  667.     MOV    DX,EBUF        ; window to the data
  668.  
  669. DOBYTES:
  670.     IN    AL,DX        ; get a byte
  671.     STOSB            ; save it to es:di
  672.     LOOP     DOBYTES
  673.  
  674.     MIN    EREC        ; get status to al, clears read
  675.     MOV    STAT,AL        ; KEEP LAST STATUS BYTE
  676. ;
  677. ;  set up to read the next packet from the net
  678. ;
  679.     MOUT    ERLOW,0        ; clear receive buffer pointer
  680.     MOUT    EAUX,EGETEM+ERIDE    ; set receive bit in aux
  681.  
  682.     MOV    AX,BX        ; return value is # of bytes
  683.     POP    ES
  684.     POP    BP
  685.     RET
  686. END_PROC    E3RECV
  687. endif
  688. ;
  689. ;************************************************************************
  690. ;  XMIT         
  691. ;     send a packet to Ethernet
  692. ;     Is not interrupt driven, just call it when you need it.
  693. ;
  694. ;  usage:   xmit(packet,count)
  695. ;        char *packet;
  696. ;        int count;
  697. ;
  698. ;   Takes a packet raw, Ethernet packets start with destination address,
  699. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  700. ;
  701. ;   checks for packets under the Ethernet size limit of 60 and handles them
  702. ;
  703. START_PROC    E3XMIT
  704.     PUSH    BP
  705.     MOV    BP,SP
  706.     PUSH    SI
  707.     PUSH    DI
  708.     PUSH    DS        ; set up proper ds for the buffer
  709.     MOV    AX,[BP+X+2]
  710.     MOV    DS,AX
  711.     MOV    SI,[BP+X]    ; offset for buffer
  712.  
  713.     MOV    AX,[BP+X+4]    ; count of bytes
  714.     MOV    CX,AX        ; save a copy, might be less than 60, ok
  715.  
  716.     CMP    AX,60        ; minimum length for Ether
  717.     JNB    OKLEN
  718.     MOV    AX,60        ; make sure size at least 60
  719. OKLEN:
  720.     MOV    BX,2048        ; total length of buffer
  721.     SUB    BX,AX        ; offset of for buffer pointer to start
  722.     MOV    DI,BX        ; save a copy of the buffer pointer
  723. ;
  724. ;  TAKE CONTROL OF THE INPUT BUFFER
  725. ;
  726.     MOUT    EAUX,EBUS+ERIDE    ; take buffer away from receiver
  727.     MOUT    ERLOW,0        ; clear receive pointer for next read
  728.     MOUTW    EGLOW,BL,BH    ; set the general purpose pointer
  729.  
  730.     MOV    DX,EBUF        ; window to packet buffer
  731.     CLD
  732. FILLBUF:
  733.     LODSB            ; get value to go into buffer
  734.     OUT    DX,AL        ; put it into buffer (autoincrement)
  735.     LOOP    FILLBUF        ; do whole count
  736.  
  737.     POP    DS
  738. ;
  739. ;  packet is in buffer, ready to be sent
  740. ;
  741. TRYAGAIN:
  742.     MOV    BX,DI        ; retrieve copy of offset pointer
  743.     MOUTW    EGLOW,BL,BH    ; set the general purpose pointer (again)
  744. ;
  745.     MOUT    EAUX,EXMIT+ERIDE    ; tell the board to send it and start receiving
  746.     
  747. NOTDONEX:
  748.     MIN    EAUX        ; waiting for transmit to finish
  749.     AND    AL,EXBUSY    ; is it done yet?
  750.     JNZ    NOTDONEX    ; no, wait some more
  751.  
  752.     MOV    CX,0        ; return value, ok
  753.     MIN    ESEND        ; get xmit status
  754.     MOV    BL,AL        ; save status
  755.     AND    AL,EDTOK    ; was it ok?
  756.     JNZ    DONEX        ; yes, successful xmit
  757. ;
  758. ;  handle the possible errors, return 1 on coll16
  759. ;     coll16 generally means that the network has failed
  760. ;
  761.     MOV    AL,BL        ; get copy of status back
  762.     AND    AL,EDTC16    ; check collision 16
  763.     JNZ    RET16        ; yes, network probably down
  764.     MOV    AL,BL        ; get copy back again
  765.     AND    AL,EDTCOLL    ; check for collision status
  766.     JZ    UNK        ; no, unknown problem
  767.     MOUT    EAUX,EBUS+ERIDE        ; collision, reset buffer control
  768.     JMP    TRYAGAIN    ; go for it
  769. UNK:
  770.     MOV    CX,2        ; unknown problem return code
  771.     JMP SHORT DONEX
  772. RET16:
  773.     MOV    CX,1        ; failure return
  774. DONEX:
  775.     MOUT    EREC,EWANT    ; reset receive register filter necessary
  776.     MIN    EAUX    
  777.     AND    AL,ERBUSY    ; is it still in receive state or done?
  778.     JNZ    DONEMIT        ; not ready now, return instead
  779.  
  780.     MOV    AL,INTNUM
  781.     CMP    AL,0BH        ; two choices of int to call
  782.     JNZ    TRYNINT
  783.     INT    0BH        ; we do have a packet, read it
  784.     JMP SHORT DONEMIT
  785. TRYNINT:
  786.     CMP    AL,0DH
  787.     JNZ    DONEMIT
  788.     INT    0DH
  789.  
  790. DONEMIT:
  791.     MOV    AX,CX        ; put return in ax
  792.     POP    DI
  793.     POP    SI
  794.     POP    BP
  795.     RET
  796. END_PROC     E3XMIT
  797. ;
  798. ;*************************************************************************
  799. ;  Interrupt Handler
  800. ;  installation and deinstallation
  801. ;
  802. ;     the handler takes the receive packet out of the input buffer
  803. ;
  804. DEINST    PROC    NEAR
  805.     MOV    CX,SAVEIP    ; get old ip from save spot
  806.     MOV    DX,SAVECS    ; get old cs from save spot
  807.     MOV    BX,WHICHINT    ; interrupt in table for 3com board
  808.     PUSH    DS
  809.     XOR    AX,AX        ; system interrupt table
  810.     MOV    DS,AX        
  811.     CLI
  812.     MOV    [BX],CX        ; store old ip into the table
  813.     INC    BX
  814.     INC    BX        ; move pointer in interrupt table
  815.     MOV    [BX],DX        ; store old cs into the table
  816.     STI
  817.     POP    DS
  818.     RET
  819. DEINST    ENDP
  820. ;
  821. IINST    PROC    NEAR
  822.     MOV    MYDS,DS        ; store for use by handler
  823.     MOV    BX,WHICHINT    ; interrupt in table for 3com board
  824.     PUSH    DS
  825.     PUSH    DS
  826.     XOR    AX,AX        ; system interrupt table
  827.     MOV    DS,AX        
  828.     MOV    AX,OFFSET DGROUP:IHAND    ; where the handler is
  829.     CLI
  830.     MOV    DX,[BX]        ; keep copy of the ip
  831.     MOV    [BX],AX        ; store ip into the table
  832.     INC    BX
  833.     INC    BX        ; move pointer in interrupt table
  834.     MOV    CX,[BX]        ; keep copy of the cs, too
  835.     POP    AX
  836.     MOV    [BX],AX        ; store new cs into the table
  837.     STI
  838.     POP    DS
  839.     MOV    SAVEIP,DX    ; store them away
  840.     MOV    SAVECS,CX
  841.     RET
  842. IINST    ENDP
  843.  
  844. ;
  845. ;*************************************************************************
  846. ;  ETUPDATE
  847. ;      update pointers and/or restart receiver when read routine has
  848. ;      already removed the current packet
  849. ;
  850. ;   usage:  etupdate();
  851. ;
  852. START_PROC    E3ETUPDATE
  853.     PUSH     ES
  854. ifdef Microsoft
  855.     MOV    AX,word ptr [_BUFPT+2]    ; establish data segment to buffer
  856. else
  857.     MOV    AX,word ptr [BUFPT+2]    ; establish data segment to buffer
  858. endif
  859.     MOV    ES,AX        ; put that in es
  860. ;
  861. ifdef Microsoft
  862.     MOV    BX,_BUFREAD    ; where read pointer is now
  863. else
  864.     MOV    BX,BUFREAD    ; where read pointer is now
  865. endif
  866.     MOV    DX,ES:[BX]    ; get size of this packet
  867.     INC    DX
  868.     INC    DX        ; two more for length value
  869.  
  870.     ADD    BX,DX        ; increment bufread by size of packet
  871.  
  872. ifdef Microsoft
  873.     MOV    CX,_BUFEND    ; right before 2K safety area
  874. else
  875.     MOV    CX,BUFEND    ; right before 2K safety area
  876. endif
  877.     CMP    BX,CX        ; see if pointer is over limit
  878.     JB    NOWRAPRD    ; we are not at wrap-around
  879.     
  880. ifdef Microsoft
  881.     MOV    BX,_BUFORG    ; wrap to here
  882. else
  883.     MOV    BX,BUFORG    ; wrap to here
  884. endif
  885. NOWRAPRD:
  886. ifdef Microsoft
  887.     MOV    _BUFREAD,BX    ; buffer pointer has been updated
  888. else
  889.     MOV    BUFREAD,BX    ; buffer pointer has been updated
  890. endif
  891.  
  892. ;
  893. ;  DECREMENT TOTAL BUFFER SIZE
  894. ;
  895.     CLI            ; keep interrupt handler from bothering dec
  896. ifdef Microsoft
  897.     MOV    CX,_BUFBIG    ; size before removing packet
  898. else
  899.     MOV    CX,BUFBIG    ; size before removing packet
  900. endif
  901.     SUB    CX,DX        ; remove size of current packet
  902. ifdef Microsoft
  903.     MOV    _BUFBIG,CX    ; put it back
  904. else
  905.     MOV    BUFBIG,CX    ; put it back
  906. endif
  907.     STI
  908. ;
  909. ;  IF RECEIVER IS ON, THEN CHECKING BUFLIM IS UNNECESSARY.
  910. ;
  911.     MOV    AL,DEAF        ; is the receiver turned off?
  912.     OR    AL,AL        ; 0 = reading, 1 = deaf
  913.     JZ    ALIVE
  914. ;
  915. ;  CHECK FOR ROOM IN THE BUFFER, IF THERE IS, TURN ON RECEIVER
  916. ;
  917. ifdef Microsoft
  918.     MOV    AX,_BUFLIM    ; what is our limit?
  919. else
  920.     MOV    AX,BUFLIM    ; what is our limit?
  921. endif
  922.     CMP    CX,AX        ; compare to limit
  923.     JA    ALIVE        ; not really alive, but can't turn on yet
  924.  
  925.     XOR    AL,AL
  926.     MOV    DEAF,AL        ; reset flag
  927.  
  928.     INC    OFFS        ; keep count how many times this happened
  929.  
  930.     MOUT    ERLOW,0        ; reset receive buffer ptr
  931.     MOUT    EAUX,EGETEM+ERIDE    ; turn on receiver
  932.  
  933. ALIVE:
  934.     POP    ES
  935.     RET    
  936. END_PROC    E3ETUPDATE
  937.  
  938. ifdef Microsoft
  939. ;_TEXT    ends
  940. else
  941.     ENDPS
  942. endif
  943.     END
  944.